package com.ynet.middleground.contract.model;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ynet.core.exception.BusinessException;
import com.ynet.host.HostConstants;
import com.ynet.middleground.contract.bean.*;
import com.ynet.middleground.contract.constant.SignServerEnum;
import com.ynet.middleground.contract.entity.ServiceRecord;
import com.ynet.middleground.contract.external.esign.ApiHelper;
import com.ynet.middleground.contract.external.esign.ApiUri;
import com.ynet.middleground.contract.external.esign.DigestHelper;
import com.ynet.middleground.contract.external.esign.EsignConfig;
import com.ynet.middleground.contract.utils.CommUtils;
import com.ynet.middleground.contract.utils.TemplateUtil;

/**
 * @author liulx
 * @description e 签宝存证相关业务处理 <br />
 *              注意，该类会在切面中记录日志 详情查看 {@link com.ynet.middleground.contract.external.aop.EviApiLogPointcut}
 * @date 2020-04-15 09:16
 */
@Component
public class EviModel {

    @Autowired
    ApiHelper apiHelper;

    @Autowired
    DigestHelper digestHelper;

    @Autowired
    EsignConfig esignConfig;

    @Autowired
    ServiceRecordModel serviceRecordModel;

    @Autowired
    CommUtils commUtils;

    /**
     * 定义所属行业类型
     *
     * @param req 定义行业所属类型请求类
     * @return 添加成功后 ID 和名称的对应列表
     */
    public Map<String, Object> createIndustryType(AddIndustryTypeReq req) {
        List<String> names = req.getNames();
        Map<String, Object> param = new HashMap<>(1);
        param.put("name", JSONArray.parseArray(JSON.toJSONString(names)));
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        JSONObject jsonObject =
            apiHelper.sendApi(headers, param, ApiUri.EVI_BUS_ADD_API, HostConstants.HTTP_METHOD_POST);
        return jsonObject.getJSONObject("result");
    }

    /**
     * 定义业务凭证（名称）
     *
     * @param req 定义业务凭证（名称）请求类
     * @return 添加成功后 ID 和名称的对应列表
     */
    public Map<String, Object> createSceneType(AddSceneTypeReq req) {
        List<String> names = req.getNames();
        Map<String, Object> param = new HashMap<>(2);
        param.put("businessTempletId", req.getBusinessTempletId());
        param.put("name", JSONArray.parseArray(JSON.toJSONString(names)));
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        JSONObject jsonObject =
            apiHelper.sendApi(headers, param, ApiUri.EVI_SCENE_ADD_API, HostConstants.HTTP_METHOD_POST);
        return jsonObject.getJSONObject("result");
    }

    /**
     * 定义业务凭证中某一证据点名称，(如：合同签署人信息)
     *
     * @param req 定义业务凭证中某一证据点名称请求类，(如：合同签署人信息)
     * @return 添加成功后 ID 和名称的对应列表
     */
    public Map<String, Object> createSegmentType(AddSegmentTypeReq req) {
        Map<String, Object> param = new HashMap<>(2);
        List<String> names = req.getNames();
        param.put("name", JSONArray.parseArray(JSON.toJSONString(names)));
        param.put("sceneTempletId", req.getSceneTempletId());
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        JSONObject jsonObject =
            apiHelper.sendApi(headers, param, ApiUri.EVI_SEG_ADD_API, HostConstants.HTTP_METHOD_POST);
        return jsonObject.getJSONObject("result");
    }

    /**
     * 定义业务凭证中某一证据点的字段属性
     * 
     * @param req 定义业务凭证中某一证据点的字段属性请求类
     * @return 添加成功后对应列表
     */
    public List<Object> createSegmentPropType(AddSegmentPropTypeReq req) {
        Map<String, Object> param = new HashMap<>(2);
        List<DisplayLinkParam> properties = req.getProperties();
        param.put("segmentTempletId", req.getSegmentTempletId());
        param.put("properties", JSONArray.parseArray(JSON.toJSONString(properties)));
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        JSONObject jsonObject =
            apiHelper.sendApi(headers, param, ApiUri.EVI_SEGPROP_ADD_API, HostConstants.HTTP_METHOD_POST);
        return jsonObject.getJSONArray("result");
    }

    /**
     * 创建证据链,获取场景式存证编号（证据链编号）
     *
     * @param req 创建证据链请求类
     * @return 场景式存证编号
     */
    public String createChainOfEvidence(AddChainOfEvidenceReq req) {
        Map<String, Object> param = new HashMap<>(3);
        param.put("sceneName", req.getSceneName());
        param.put("sceneTemplateId", req.getSceneTemplateId());
        param.put("linkIds", JSONArray.parseArray(JSON.toJSONString(req.getLinkIds())));
        String paramJsonString = JSON.toJSONString(param);
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(paramJsonString);
        // 记录签名操作日志，以供内管查询使用
        ServiceRecord record = new ServiceRecord();
        record.setRequestMsg(paramJsonString);
        record.setSceneDesc(req.getSceneName());
        try {
            JSONObject jsonObject =
                apiHelper.sendApi(headers, param, ApiUri.EVI_VOUCHER_API, HostConstants.HTTP_METHOD_POST);
            String evid = jsonObject.getString("evid");
            record.setServiceStatus(true);
            record.setEvid(evid);
            serviceRecordModel.insertServiceRecord(record, SignServerEnum.EVIDENCE, req);
            return evid;
        } catch (BusinessException e) {
            record.setServiceStatus(false);
            serviceRecordModel.insertServiceRecord(record, SignServerEnum.EVIDENCE, req);
            throw e;
        }
    }

    /**
     * 创建摘要存证证据点
     *
     * @param req 创建摘要存证证据点请求类
     * @return 摘要存证证据点ID
     */
    public String createSegmentOriginalDigest(AddSegmentOriginalDigestReq req) {
        String fileUrl = req.getFileUrl();
        String segmentData = req.getSegmentData();
        JSONObject content = new JSONObject();
        Map<String, Object> param = new HashMap<>(3);
        // step1:判空
        if (StringUtils.isBlank(fileUrl) && StringUtils.isBlank(segmentData)) {
            throw new BusinessException("文档 OSS 地址，与业务数据不可同时为空", "ECCT0001");
        }
        // step2.1 整理fileUrl参数相关
        if (!StringUtils.isBlank(fileUrl)) {
            fileUrl = commUtils.transferFileUrl(fileUrl);
            String suffix = fileUrl.substring(fileUrl.lastIndexOf("."));
            File file = TemplateUtil.getFileByUrl(fileUrl, suffix);
            // 待保全文档名称（文件名中不允许含有? * : " < > \ / | [ ] 【】）
            content.put("contentDescription", file.getName());
            // 原文SHA256摘要
            String fileDigestSHA256 = digestHelper.getFileSHA256(file);
            content.put("contentDigest", fileDigestSHA256);
            param.put("content", content);
        }
        // step2.2 整理segmentData参数相关
        if (!StringUtils.isBlank(segmentData)) {
            param.put("segmentData", req.getSegmentData());
        }
        param.put("segmentTempletId", req.getSegmentTempletId());
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        // step3: 转调
        JSONObject jsonObject =
            apiHelper.sendApi(headers, param, ApiUri.EVI_ORIGINAL_DIGEST_API, HostConstants.HTTP_METHOD_POST);
        return jsonObject.getString("evid");
    }

    /**
     * 追加证据点，将证据点追加到已存在的证据链内形成证据链
     * 
     * @param req 追加证据点请求类
     */
    public void appendEvidence(AppendEvidenceReq req) {
        Map<String, Object> param = new HashMap<>(2);
        param.put("evid", req.getEvid());
        param.put("linkIds", JSONArray.parseArray(JSON.toJSONString(req.getLinkIds())));
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        apiHelper.sendApi(headers, param, ApiUri.EVI_VOUCHER_APPEND_API, HostConstants.HTTP_METHOD_POST);
    }

    /**
     * 将场景式存证编号与用户的证件号进行关联
     * 
     * @param req 数据存证编号关联到指定用户请求类
     */
    public void relateSceneEvIdWithUser(RelateSceneEvIdWithUserReq req) {
        Map<String, Object> param = new HashMap<>(2);
        param.put("evid", req.getEvid());
        param.put("certificates", JSONArray.parseArray(JSON.toJSONString(req.getCertificates())));
        LinkedHashMap<String, String> headers = apiHelper.getPOSTHeaders(JSON.toJSONString(param));
        apiHelper.sendApi(headers, param, ApiUri.EVI_RELATE_API, HostConstants.HTTP_METHOD_POST);
    }

    /**
     * 存证证明查看页面链接
     * 
     * @param req 存证证明查看页面链接请求类
     * @return 存证证明页面查看地址
     */
    public String getEviViewPageUrlReq(GetEviViewPageUrlReq req) {
        StringBuilder param = new StringBuilder();
        param.append("id=").append(req.getId());
        param.append("&projectId=").append(esignConfig.getProjectId());
        param.append("&timestamp=").append(req.getTimestamp());
        param.append("&reverse=").append(req.getReverse());
        param.append("&type=").append(req.getType());
        param.append("&number=").append(req.getNumber());
        // 请求签名值
        String signature = digestHelper.getSignature(param.toString(), esignConfig.getProjectSecret(),
            esignConfig.getEviAlgorithm(), esignConfig.getEviEncoding());
        return esignConfig.getEviViewpageHost() + ApiUri.EVI_VIEWPAGE_URL + "?" + param.toString() + "&signature="
            + signature;
    }

}
